using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;

namespace Colman.Rpg.Npc
{
    /// <summary>
    /// Displays an NPC world.
    /// </summary>
    public partial class WorldDisplayControl : UserControl
    {
        private Tile[,] mapTiles;

        /// <summary>
        /// Creates a new instance of <see cref="WorldDisplayControl" />.
        /// </summary>
        public WorldDisplayControl()
        {
            InitializeComponent();

            this.SetStyle(ControlStyles.Selectable, false);

            this.TilesSeen = 7;
        }

        #region int TilesSeen { get; set; } (tilesSeen)
        private int tilesSeen;

        /// <summary>
        /// Gets or sets the number of tiles seen in the map.
        /// </summary>
        [DefaultValue(7)]
        public int TilesSeen
        {
            [System.Diagnostics.DebuggerStepThrough]
            get
            {
                return this.tilesSeen;
            }
            [System.Diagnostics.DebuggerStepThrough]
            set
            {
                if (value <= 0)
                    throw new ArgumentOutOfRangeException("value");

                if (this.tilesSeen != value)
                {
                    this.tilesSeen = value;

                    this.Controls.Clear();

                    this.mapTiles = new Tile[value, value];

                    for (int i = 0; i < value; i++)
                    {
                        for (int j = 0; j < value; j++)
                        {
                            Tile tile = new Tile();

                            tile.Location = new Point(i * tile.Width, j * tile.Height);
                            this.Controls.Add(tile);

                            this.mapTiles[i, j] = tile;
                        }
                    }

                    this.Size = new Size(this.mapTiles[0, 0].Width * value, this.mapTiles[0, 0].Height * value);
                }
            }
        }
        #endregion

        #region World DataSource { get; set; } (dataSource)
        private World dataSource;

        /// <summary>
        /// Gets or sets the source of data for the world.
        /// </summary>
        public World DataSource
        {
            [System.Diagnostics.DebuggerStepThrough]
            get
            {
                return this.dataSource;
            }
            [System.Diagnostics.DebuggerStepThrough]
            set
            {
                if (this.dataSource != value)
                {
                    this.dataSource = value;

                    this.SnapToPlayer();
                }
            }
        }
        #endregion

        /// <summary>
        /// Snaps the view to the player's current location.
        /// </summary>
        public void SnapToPlayer()
        {
            int x = this.dataSource.PlayerPosition.X - this.tilesSeen / 2;

            if (x < 0)
                x += this.dataSource.Size;

            int y = this.dataSource.PlayerPosition.Y - this.tilesSeen / 2;

            if (y < 0)
                y += this.dataSource.Size;

            for (int i = 0; i < this.tilesSeen; i++)
            {
                if (x + i >= this.dataSource.Size)
                    x = -i;

                int oldY = y;

                for (int j = 0; j < this.tilesSeen; j++)
                {
                    if (y + j >= this.dataSource.Size)
                        y = -j;

                    this.mapTiles[i, j].Type = this.dataSource[x + i, y + j];
                }

                y = oldY;
            }
        }
    }
}
